<?php


class Post extends Model
{
	var $id = null;
	var $title;
	var $body;
	var $active = 1;
	var $online = 1;
	var $creator_id;
	var $created_at;
	var $updater_id;
	var $updated_at;

	function Post()
	{
		parent::Model();
		$this->load->model('Tag');
	}

	function get_by_id($id)
	{
		$this->db->select('p.id, p.title, p.body, p.online, p.creator_id, p.created_at, p.updater_id, p.updated_at, u.firstname as creator_firstname, u.name as creator_name, u2.firstname as updater_firstname, u2.name as updater_name')
			     ->from('post p')
			     ->join('user u', 'p.creator_id = u.id')
			     ->join('user u2', 'p.updater_id = u2.id')
				 ->where('p.id', $id)
				 ->where('p.active', 1);
		$query = $this->db->get();
		return $query->row();
	}

	function plain_get($id)
	{
		$this->db->select('id, title, body, online, created_at, updated_at')
		         ->from('post')
		         ->where('id', $id)
		         ->where('active', 1);
		$query = $this->db->get();
		return $query->row();
	}

	/**
	 * Obtenir une page d'actualités
	 */
	function get_page($page_num)
	{
		$first = ($page_num - 1) * POSTS_PER_PAGE;
		$this->db->select('id, title, body, created_at')
			     ->from('post')
			     ->where('active', 1)
				 ->where('online', 1)
			     ->order_by('created_at DESC')
			     ->limit(POSTS_PER_PAGE, $first);
		$query = $this->db->get();
		return $query->result();
	}

	/**
	 * Nombre de pages de posts
	 */
	function get_nb_pages()
	{
		$this->db->select('count(id) as nb_posts')
		         ->from('post')
		         ->where('active', 1)
				 ->where('online', 1);
		$result = $this->db->get()->result();
		return ceil($result[0]->nb_posts / POSTS_PER_PAGE);
	}

	function get_by_tag($tag_id)
	{
		$this->db->select('p.id, p.title, p.body, p.online, p.creator_id, p.created_at, p.updater_id, p.updated_at, u.firstname as creator_firstname, u.name as creator_name, u2.firstname as updater_firstname, u2.name as updater_name')
			     ->from('post p')
			     ->join('user u', 'p.creator_id = u.id')
			     ->join('user u2', 'p.updater_id = u2.id')
			     ->join('post_tag pt', 'p.id = pt.post_id')
				 ->where('p.online', 1)
				 ->where('p.active', 1)
				 ->where('pt.tag_id', $tag_id);
		$query = $this->db->get();
		return $query->result();
	}

	/**
	 * Liste de tous les posts
	 */
	function all()
	{
		$this->db->select('p.id, p.title, p.online, p.created_at, u.name as creator_name, u.firstname as creator_firstname')
		         ->from('post p')
		         ->join('user u', 'u.id = p.creator_id')
		         ->where('p.active', 1);
		$query = $this->db->get();
		return $query->result();
	}

	/**
	 * Tous les posts publiés
	 */
	function onlines()
	{
		$this->db->select('id, title, created_at, updated_at')
		         ->from('post')
				 ->where('active', 1)
				 ->where('online', 1);
		$query = $this->db->get();
		return $query->result();
	}

	/**
	 * Sauvegarder le post
	 * (insert si nouveau post, update si post déjà existant)
	 */
	function save($post)
	{
		$result = null;
		if ($post->id == null) {
			$result = $this->db->insert('post', $post);
			$post->id = $this->db->insert_id();
		}
		else {
			$this->db->where('id', $post->id);
			$result = $this->db->update('post', $post);
		}
		$this->generate_rss();
		return $result;
	}

	/**
	 * Supprimer un post
	 */
	function delete($id)
	{
		$sql = 'UPDATE post
		        SET active = 0
				WHERE id = '.intval($id).';';
		return $this->db->query($sql);
	}

	function restore($id)
	{
		$sql = 'UPDATE post
		        SET active = 1
				WHERE id = '.intval($id).';';
		return $this->db->query($sql);
	}

	/**
	 * Vérifier et affecter les données utlisateurs
	 * @return liste des erreurs
	 */
	function update(&$post, &$data)
	{
		$errors = array();
		if (empty($data['title'])) {
			$errors[] = 'Le titre ne peut pas être vide';
		}
		else {
			$post->title = clean_str($data['title']);
		}
		if (empty($data['body'])) {
			$errors[] = 'Le contenu ne peut pas être vide';
		}
		else {
			$post->body = clean_str_preserve_tags($data['body']);
		}
		$post->online = isset($data['online']);
		return $errors;
	}

	function update_tags(&$post, $tags_string)
	{
		// extraction depuis la chaîne des tags
		$tag_names = array();
		foreach (array_unique(explode(';', $tags_string)) as $tag_name) {
			$tag_name = clean_str($tag_name);
			if ($tag_name) {
				$tag_names[] = $tag_name;
			}
		}
		// enregistrement des tags
		$this->remove_tags($post->id);
		foreach ($tag_names as $tag) {
			$this->add_tag($post->id, $tag);
		}
		return $tag_names;
	}

	/**
	 * Générer le flux xml des posts
	 */
	function generate_rss()
	{
		$rss = fopen(POSTS_RSS_FEED, 'w');
		if ($rss)
		{
			fputs($rss, '<?xml version="1.0" encoding="utf-8" ?>'."\n");
			fputs($rss, '<rss version="2.0">'."\n");
			fputs($rss, "\t<channel>\n");
			fputs($rss, "\t\t<title>Licence MIAGE Paris Descartes</title>\n");
			fputs($rss, "\t\t<link>".base_url()."</link>\n");
			fputs($rss, "\t\t<description>Les dernières actualités</description>\n");
			fputs($rss, "\t\t<lastBuildDate>".date('r', time())."</lastBuildDate>\n");
			fputs($rss, "\t\t<language>fr</language>\n");

			$posts = $this->get_page(1);
			foreach ($posts as $post)
			{
				fputs($rss, "\t\t<item>\n");
				fputs($rss, "\t\t\t<title>".$post->title."</title>\n");
				fputs($rss, "\t\t\t<link>".base_url()."news/show/".$post->id."</link>\n");
				fputs($rss, "\t\t\t<description>".html_entity_decode(strip_tags($post->body), ENT_QUOTES, 'UTF-8')."</description>\n");
				$d = new DateTime($post->created_at);
				fputs($rss, "\t\t\t<pubDate>".$d->format('r')."</pubDate>\n");
				fputs($rss, "\t\t</item>\n");
			}
			fputs($rss, "\t</channel>\n");
			fputs($rss, "</rss>\n");
			fclose($rss);
		}
	}

	function tags($post_id)
	{
		$this->db->select('t.id, t.name, t.created_at, t.updated_at')
		         ->from('tag t')
		         ->join('post_tag pt', 'pt.tag_id = t.id', 'left')
		         ->where('pt.post_id', $post_id)
		         ->order_by('t.name');
		$query = $this->db->get();
		return $query->result();
	}

	function all_tags($filter = null)
	{
		$this->db->select('t.id, t.name, t.created_at, t.updated_at, COUNT(pt.post_id) as post_count')
		         ->from('tag t')
		         ->join('post_tag pt', 'pt.tag_id = t.id')
		         ->join('post p', 'p.id = pt.post_id')
		         ->where('p.active', 1)
		         ->group_by('t.id')
		         ->order_by('t.name');
		if ($filter) {
			$this->db->where($filter);
		}
		$query = $this->db->get();
		return $query->result();
	}

	function tag_cloud()
	{
		// tags de les posts onlines
		$tags = $this->all_tags('p.online = 1');

		// recherche poids min et max des tags
		$weight_min = null;
		$weight_max = null;
		foreach ($tags as $tag) {
			if ($weight_min == null || $tag->post_count < $weight_min) {
				$weight_min = $tag->post_count;
			}
			if ($weight_max == null || $tag->post_count > $weight_max) {
				$weight_max = $tag->post_count;
			}
		}
		$weight_diff = $weight_max - $weight_min;
		if ($weight_diff == 0) {
			$weight_diff = 1;
		}
		$font_min = 10;
		$font_max = 25;
		$font_diff = $font_max - $font_min;

		$anchors = array();
		// on calcule la taille de la police pour chaque tag, de façon proportionnelle
		// à son nombre de posts (= poids) sur l'échelle $font_min -> $font_max
		// un tag de poids $weight_min aura une police de taille $font_min,
		// un tag de poids $weight_max aura une police de taille $font_max.
		foreach ($tags as $tag) {
			$font_size = (($tag->post_count - 1) * $font_diff / floatval($weight_diff)) + $font_min;
			$link = 'news/tagged/'.Tag::friendly_url($tag);
			$anchors[] = anchor($link, $tag->name, ' style="font-size: '.$font_size.'px;" title="'.$tag->post_count.' article(s)"');
		}
		return $anchors;
	}

	function add_tag($post_id, $tag_name)
	{
		$tag = $this->Tag->get_by_name($tag_name);
		if (!$tag) {
			$tag = new Tag();
			$tag->name = $tag_name;
			$this->Tag->save($tag);
		}
		$sql = 'insert into post_tag (tag_id, post_id)
		        values ('.$tag->id.', '.intval($post_id).')';
		$this->db->query($sql);
	}

	function remove_tags($post_id)
	{
		$post_id = intval($post_id);
		$sql = 'delete from post_tag
		        where post_id = '.$post_id.';';
		return $this->db->query($sql);
	}
}
